package com.zeng.sim.support.server.socket;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 描述信息
 *
 * @author zengwanlin
 * @date 2023-12-25T13:42
 */
public class ServerSimSocket implements Runnable {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServerSimSocket.class);

    private ServerSocket serverSocket;

    private ThreadPoolExecutor busiPoolExecutor = null;

    private final AtomicBoolean runFlag = new AtomicBoolean(false);

    public ServerSimSocket(Integer listenPort, ThreadPoolExecutor busiPoolExecutor) {
        try {
            serverSocket = new ServerSocket(listenPort);
        }
        catch (IOException e) {
            throw new IllegalStateException("初始化ServerSocket异常，" + e.getMessage(), e);
        }
        this.busiPoolExecutor = busiPoolExecutor;

        runFlag.set(true);

        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            runFlag.set(false);
            try {
                LOGGER.info("关闭模拟服务端-Socket服务-监听");
                serverSocket.close();
            }
            catch (IOException e) {
                LOGGER.error(e.getMessage(), e);
            }

            LOGGER.info("关闭模拟器-业务线程池");
            this.busiPoolExecutor.shutdown();
            try {
                long timeToWait = 30L;
                if (!this.busiPoolExecutor.awaitTermination(timeToWait, TimeUnit.SECONDS)) {
                    this.busiPoolExecutor.shutdownNow();
                    if (!this.busiPoolExecutor.awaitTermination(timeToWait, TimeUnit.SECONDS)) {
                        LOGGER.warn("关闭模拟器-业务线程池-失败");
                    }
                }
            }
            catch (InterruptedException e) {
                this.busiPoolExecutor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }));
    }

    @Override
    public void run() {
        while (runFlag.get()) {
            try {
                Socket socket = serverSocket.accept();
                busiPoolExecutor.execute(new ServerSimSocketHandler(socket));
            }
            catch (IOException e) {
                LOGGER.error(e.getMessage(), e);
            }
        }
    }

}
